/**************************************************************
  > File Name: sem.c
  > Author: LuoLiang
  > Mail: 1204553475@qq.com 
  > Created Time: 2022年02月24日 星期四 02时55分04秒
 **************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/shm.h>
#include <sys/wait.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <errno.h>

#define PATHNAME "/tmp/out"
#define SIZE 4096
#define BUFSIZE 1024

static int semid;

static void P()
{
	
	struct sembuf sops;

	sops.sem_num = 0;
	sops.sem_op = -1;
	sops.sem_flg = SEM_UNDO;
	while (semop(semid, &sops, 1) < 0)
	{
		if (errno != EAGAIN || errno != EINTR)
		{
			perror("semop()");
			exit(1);
		}
	}
}

static void V()
{
	struct sembuf sops;

	sops.sem_num = 0;
	sops.sem_op = 1;
	sops.sem_flg = SEM_UNDO;
	while (semop(semid, &sops, 1) < 0)
	{
		if (errno != EAGAIN || errno != EINTR)
		{
			perror("semop()");
			exit(1);
		}
	}

}

int main(int argc, char **argv)
{
	key_t key;
	int proj_id = 1;
	int shmid;
	char buf[BUFSIZE] = {0};
	pid_t pid;
	int semval;
	char *shmp = NULL;
	int i = 100000LL;

	key = ftok(PATHNAME, proj_id);
	if (key < 0)
	{
		perror("ftok()");
		exit(1);
	}

	shmid = shmget(key, SIZE, IPC_CREAT | 0666);
	if (shmid < 0)
	{
		perror("shmget()");
		exit(1);
	}
	
	shmp = shmat(shmid, NULL, 0);
	if (shmp == NULL)		
	{
		perror("shmat()");
		exit(1);
	}
	
	semid = semget(key, 1, IPC_CREAT | 0666);
	if (semid < 0)
	{
		perror("semget()");
		exit(1);
	}
	
	semval = 1;
	if (semctl(semid, 0, SETVAL, semval) < 0)
	{
		perror("semctl()");
		exit(1);
	}

	pid = fork();
	if (pid < 0)
	{
		perror("fork()");
		exit(1);
	}
	if (pid == 0)
	{
		while (i--)
		{
			P();
			strcpy(shmp, "hello linux");
			V();
		}
		exit(0);
	}
	else
	{
		while (i--)
		{
			P();
			strcpy(shmp, "i am cj");
			V();
			strcpy(buf, shmp);
			puts(buf);
		}
		wait(NULL);
		shmdt(shmp);
		semctl(semid, 0, IPC_RMID);
	}	

    exit(0);
}
